package org.afei.ioc.container;

import org.afei.ioc.data.DataContext;
import org.afei.ioc.entity.BeanEntity;
import org.afei.ioc.entity.ServiceEntity;
import org.afei.ioc.exception.BeansException;
import org.afei.ioc.factory.AbstractBeanFactory;
import org.afei.ioc.util.ReflectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * 使用工厂模式和策略模式实现容器内部具体工厂的动态加载
 *
 * @author afei
 * @date 17-5-25.
 */
public class DefaultContainer implements Container {

    private static final Logger LOGGER =
            LoggerFactory.getLogger(DefaultContainer.class);

    private AbstractBeanFactory factory;

    /**
     * @param map 值取自配置文件，因为可以加载不同的factory实现，同时定制factory的组件。
     */
    public DefaultContainer(Map<String, Object> map) {
        LOGGER.info("----------开始初始化容器---------");

        //这个默认工厂的读取应该来自配置文件
        //如果无自定义信息，自动加载默认的工厂实现
        System.out.println("----------开始初始化容器内工厂---------");

        factory = (AbstractBeanFactory) ReflectionUtil.getInstance(map.get("factory") == null ?
                "org.afei.ioc.factory.DefaultBeanFactory" : map.get("factory").toString());

        factory.registerBeanDefinition(map.get("resource") == null ?
                        "org.afei.ioc.bean" : map.get("resource").toString()
                , map.get("cacheContext") == null ?
                        "org.afei.ioc.data.DefaultBeanCacheContext" : map.get("cacheContext").toString()
                , map.get("definitionContext") == null ?
                        "org.afei.ioc.data.DefaultBeanDefinitionContext" : map.get("definitionContext").toString()
                , map.get("defaultHandler") == null ?
                        "org.afei.ioc.handler.DefaultAnnotationHandler" : map.get("defaultHandler").toString()
                , map.get("customHandler") == null ?
                        null : map.get("customHandler").toString()
        );

        LOGGER.info("----------初始化容器内工厂成功！---------");
        LOGGER.info("----------初始化容器成功！---------");
    }

    /**
     * 这里使用外观模式，container即是factory的外观
     *
     * @param name
     * @return
     */
    @Override
    public Object getBean(String name) {
        return factory.getBean(name);
    }

    @Override
    public <T> T getBean(String name, Class<T> clazz) {
        return factory.getBean(name, clazz);
    }

    public Object getService(String beanName, String serviceName, Object... args)
            throws BeansException {

        DataContext beanDefinitionContext = factory.getBeanDefinitionContext();
        BeanEntity beanEntity = (BeanEntity) beanDefinitionContext.get(beanName);
        if (null == beanEntity) {
            throw new BeansException("the beanEntity is null");
        }
        String method = null;
        for (ServiceEntity serviceEntity : beanEntity.getServiceEntityList()) {
            if (serviceName.equals(serviceEntity.getName())) {
                method = serviceEntity.getValue();
            }
        }
        //如果直接反射实例，不会注入依赖服务，不会缓存，这里一方面是为了缓存，另一方面是为了工厂的扩展。
        Object obj = getBean(beanName);
        Object result = ReflectionUtil.invoke(obj, ReflectionUtil.getMethod(obj, method), args);
        System.out.println(result.toString());
        return result;
    }

    public DataContext getBeanDefinitionContext() {
        return factory.getBeanDefinitionContext();
    }

    public BeanEntity getBeanDefinition(String name) {
        return (BeanEntity) getBeanDefinitionContext().get(name);
    }

    public DataContext getBeanCacheContext() {
        return factory.getBeanCacheContext();
    }

    public void initContainerService(String resource) {
        //TODO：热部署，动态改变容器中服务的状态，需要调用该方法
    }

}
